package com.javaweb.handler;

import java.util.List;
import java.util.Objects;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.http.server.ServletServerHttpRequest;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.javaweb.base.BaseInject;
import com.javaweb.base.BaseResponseResult;
import com.javaweb.base.po.Interfaces;
import com.javaweb.constant.CommonConstant;
import com.javaweb.constant.SystemConstant;
import com.javaweb.constant.SystemConstant.HeadConstant;
import com.javaweb.util.core.ObjectOperateUtil;
import com.javaweb.util.core.SecretUtil;
import com.javaweb.web.eo.TokenData;
import com.javaweb.web.eo.interfaces.ExcludeInfoResponse;

import jakarta.servlet.http.HttpServletRequest;

/**
 * 全局返回值处理
 * @author tank2140896
 */
@RestControllerAdvice(basePackages={SystemConstant.DEFAULT_GLOBAL_CONTROLLER_PACKAGE})
public class GlobalResponseBodyHandler implements ResponseBodyAdvice<Object>{
	
	@Override
	public Object beforeBodyWrite(Object object,MethodParameter methodParameter,MediaType mediaType,Class<? extends HttpMessageConverter<?>> c,ServerHttpRequest serverHttpRequest,ServerHttpResponse serverHttpResponse) {
		if(object instanceof BaseResponseResult baseResponseResult){
			//String path = serverHttpRequest.getURI().getPath();
			HttpServletRequest httpServletRequest = ((ServletServerHttpRequest)serverHttpRequest).getServletRequest();
			Interfaces interfaces = (Interfaces)httpServletRequest.getAttribute(SystemConstant.REQUEST_URL_CHAIN_ATTRIBUTE_NAME);
			if(interfaces!=null){
				baseResponseResult = this.dataPermissionHandle(serverHttpRequest,interfaces,baseResponseResult);
				if(interfaces.getResponseDataSecret()==1) {//表示接口返回需要加密
					//返回加密这里做的简单点了，可以根据需要自行强化处理
					//System.out.println(JSONObject.fromObject(baseResponseResult).toString());
					baseResponseResult = this.easySecretResponseData(baseResponseResult,serverHttpResponse);
				}
			}
			return baseResponseResult;
		}else{
			return object;
		}
	}

	@Override
	public boolean supports(MethodParameter methodParameter,Class<? extends HttpMessageConverter<?>> c) {
		return true;
	}
	
	//数据权限处理
	private BaseResponseResult dataPermissionHandle(ServerHttpRequest serverHttpRequest,Interfaces interfaces,BaseResponseResult baseResponseResult) {
		try{
			TokenData tokenData = BaseInject.getTokenData(BaseInject.getToken(serverHttpRequest));
			if(tokenData!=null){
				if(interfaces.getDataPermission()==1) {
					List<ExcludeInfoResponse> excludeInfoResponseList = tokenData.getExcludeInfoResponseList();
					if(!CollectionUtils.isEmpty(excludeInfoResponseList)) {
						for(int i=0;i<excludeInfoResponseList.size();i++){
							ExcludeInfoResponse excludeInfoResponse = excludeInfoResponseList.get(i);
							if(Objects.equals(interfaces.getUrl(),excludeInfoResponse.getUrl())){
								String out = ObjectOperateUtil.excludeField(baseResponseResult,excludeInfoResponse.getExcludeField().split(CommonConstant.COMMA),false).toString();
								baseResponseResult = new ObjectMapper().readValue(out,BaseResponseResult.class);
								break;
							}
						}
					}
				}
			}
		}catch(Exception e){
			//do nothing
		}
		return baseResponseResult;
	}
	
	//加密返回数据
	private BaseResponseResult easySecretResponseData(BaseResponseResult baseResponseResult,ServerHttpResponse serverHttpResponse) {
		String nonce = SecretUtil.defaultGenRandomPass(SecretUtil.MOST_COMMONLY_USED_STRING,24);
		try {
			String data = new ObjectMapper().writeValueAsString(baseResponseResult.getData());
			baseResponseResult.setData(SecretUtil.encryptAes(data,nonce));
		}catch (Exception e) {
			//do nothing
		}
		serverHttpResponse.getHeaders().add(HeadConstant.RESPONSE_HEADER_NONCE,nonce);
		return baseResponseResult;
	}

}
